-- SkyCombatM
-- created by panyl
-- 空战战斗模块

module("SkyCombatM", package.seeall);

local battle = nil;
local skyCombatEffectTable = {};

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 天空战斗光效配置
    skyCombatEffectTable = {};
    local effect_CSV = get_sky_combat_effect_CSV();
    for i = 1, #effect_CSV do
        local effect = effect_CSV[i].effect;
        skyCombatEffectTable[effect] = effect_CSV[i];
    end
    effect_CSV = nil;
end

-- 模块初始化操作
function init()
    loadCsv();

    EventMgr.removeAll("SkyCombatM");

    -- 战斗结束了，干掉战场
    EventMgr.register("SkyCombatM", event.SKY_COMBAT_END, function(para)
        battle = nil;
    end);

    -- 播放序列为空，尝试下一行为
    EventMgr.register("SkyCombatM", event.SKY_COMBAT_SEQUENCEN_FREE, function(para)
        if not battle then
            return;
        end

        battle:nextAction();
    end);
end

-- 获取战场
function getBattle()
    return battle;
end

-- 创建一个战场
function createBattle(attacker, defenser, result, record, bonus, extraData)
    -- 创建一个战场
    battle = SkyBattle.create(attacker, defenser, result, record, bonus);
    battle.extraData = extraData;

    -- 抛出事件
    EventMgr.fire(event.START_SKY_BATTLE, {["battle"] = battle, });

    return battle;
end

-- 玩家舰队战力
-- @param camp用于计算战力的冈布奥列表，如果没有传入，则默认使用当前出战的冈布奥列表
function calcArmyAbility(camp)
    local camp = camp or ME.user.dbase:query("activedSkyGroup");

    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});

    local list = skyGroup[camp];
    if not list then
        return 0;
    end

    local ability = 0;
    for _, classId in pairs(list) do
        local pet = ME.user.pets[classId];
        if pet then
            local petAbility = FormulaM.invoke("CALC_SINGLE_PET_ABILITY", pet)
            ability = ability + petAbility;
        end
    end

    -- 机器人加成
    local robotAddon = SkyRobotM.getRobotAddon(camp);
    ability = ability + (robotAddon["fight_ability"] or 0);

    -- 天空战能力加成
    local prop = PropM.combine(ME.user, "sky_attrib", "fight_ability");
    ability = PropM.apply(prop, ability);

    -- 天空战附加属性加成
    local skyProp = SkyPropM.refreshSkyProp(ME.user, list);
    ability = ability + SkyPropM.calcAddonByData({["sky_prop"] = skyProp}, "fight_ability", ability);

    return ability;
end

-- 当前所有出战的宠物
function getSkyArmy()
    local index = ME.user.dbase:query("activedSkyGroup");
    if not index then
        return {};
    end

    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});
    if not skyGroup[index] then
        return {};
    end

    return skyGroup[index];
end

-- 某只宠物是否出战中
function isInArmy(classId)
    local index = ME.user.dbase:query("activedSkyGroup");
    if not index then
        return false;
    end

    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});
    if not skyGroup[index] then
        return false;
    end

    return table.indexOf(skyGroup[index], classId) > 0;
end

-- 某只宠物是否在某个编组出战中
function isInGroup(classId, index)
    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});
    if not skyGroup[index] then
        return false;
    end

    return table.indexOf(skyGroup[index], classId) > 0;
end

-- 获取编组
function getGroup(camp)
    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});

    return skyGroup[camp] or {};
end

-- 保存编组
function saveGroup(camp, actived, activedType, unload, unloadType)
    local petGroup = getGroup(camp);
    local robotGroup = SkyRobotM.getRobotsByCamp(camp);

    -- 先尝试下阵
    if unload and unloadType then

        if unloadType == "pet" then
            table.removeItem(petGroup, unload);
        else
            robotGroup[unload] = robotGroup[unload] - 1;
            if robotGroup[unload] == 0 then
                robotGroup[unload] = nil;
            end
        end
    end

    -- 出战
    if actived and activedType then
        if activedType == "pet" then
            table.insert(petGroup, actived);
        else
            robotGroup[actived] = 1 + (robotGroup[actived] or 0);
        end
    end

    -- 先保存机器人
    SkyRobotM.saveRobotGroup(camp, robotGroup);

    -- 保存冈布奥
    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});
    skyGroup[camp] = petGroup;

    ME.user.dbase:set("skyArmyGroup", skyGroup);

    Operation.cmd_save_sky_group(camp, petGroup, robotGroup);

    EventMgr.fire(event.SKY_CITY_SAVE_GROUP, { ["actived"] = actived, ["activedType"] = activedType,
        ["unload"] = unload, ["unloadType"] = unloadType});
    return true;
end

-- 出战
function activeGroup(camp)
    local skyGroup = ME.user.dbase:query("skyArmyGroup", {});

    -- 预先设置出战编组
    ME.user.dbase:set("activedSkyGroup", camp);

    Operation.cmd_active_sky_group(camp);

    -- 抛出天空之城编组出战事件
    EventMgr.fire(event.SKY_ACTIVE_GROUP, { ["camp"] = camp });
    return true;
end

-- 获取最大可派遣的冈布奥数量
function getMaxPetNum()
    return ME.user:queryAttrib("army_number") or 10;
end

-- -- 切换出战状态
-- function switchPetState(classId)
--     -- 直接发送消息
--     local state = iif(isInArmy(classId), 0, 1);

--     Communicate.send("CMD_SEND_TO_ARMY", {["class_id"] = classId, ["state"] = state, });
-- end



-- 修正伤害
function fixDamage(source, target)
    -- 基础伤害
    local damage = source:queryAttrib("attack");

    -- 己方火力等级和敌方装甲等级
    local fire = source:queryAttrib("fire");
    local armor = source:queryAttrib("armor");

    local t = fire - armor;

    if t >= 0 then
        damage = damage + math.modf(damage * t / 100);
    else
        damage = damage +  math.modf(damage * t / (100 - t));
    end

    return damage;
end

-- 技能攻击
function skillAttack(source, target, skillId, value, round)
    -- 如果是闪避掉了
    if value == "dodge" then
        -- TODO:
        trace("SkyCombatM", "%s 闪避。", target:getName());
        return { ["damage"] = 0, ["cure"] = 0, };
    end

    -- 走飞艇技能模块
    return SkyShipSkillM.apply(source, target, skillId, round, value);
end

-- 每回合属性处理
function propHandle(who, round)
    local arr = who.dbase:queryTemp("prop", {});
    local triggerMap = {};
    local props = {};

    for path, list in pairs(arr) do
        local validProp = {};

        for index, prop in pairs(list) do
            -- 如果已经过期了
            if prop[4] ~= -1 and prop[4] <= round then
                -- TODO:
            else
                -- 未过期，收集起来
                table.insert(validProp, prop);

                if PropM.query(prop[1], "trigger") == "round" then
                    triggerMap[prop[1]] = prop[2];
                end
            end
        end

        if #validProp > 0 then
            props[path] = validProp;
        end
    end

    who.dbase:setTemp("prop", props);

    -- 重整一下属性
    PropM.arrangeProps(who);

    local ret = {};
    for propId, key in pairs(triggerMap) do
        local result = PropM.trigger(who, propId, key);

        if type(result) == "table" then
            for key, value in pairs(result) do
                if not ret[key] then
                    ret[key] = {};
                end

                table.insert(ret[key], value);
            end
        end
    end

    return ret;
end

-- 处理服务器下发的回合触发属性处理结果
function roundPropApply(attacker, defenser, propValue)
    -- 分别处理下攻击方和防守方的回合触发属性
    -- 触发的结果服务器已经计算好了，这里直接起效就可以
    for _, fighter in ipairs({attacker, defenser}) do
        local data = propValue[fighter.dbase:query("pos") - 1];

        if type(data) == "table" then
            for _, info in ipairs(data) do
                if type(info["damage"]) == "number" then
                    fighter:receiveDamage(info["damage"]);
                elseif type(info["cure"]) == "number" then
                    fighter:addAttrib("hp", info["cure"]);
                end
            end
        end

    end
end

-- 获取回合
function getRound()
    return battle.round;
end

-- 获取天空战斗光效配置
function queryEffect(effect)
    return skyCombatEffectTable[effect] or {};
end